package com.ls.fw.office.poi.excel;
/**

 * @ProjectName: 

 * @Copyright: 2014 lisheng  All Right Reserved.

 * @address: toughheart@163.com

 * @date: 2015年10月8日 下午10:16:44

 * @Description: 本内容未经本人允许禁止使用、转发.

 */



import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ls.fw.commons.core.utils.collections.MapUtils;
import com.ls.fw.commons.core.utils.collections.MapUtils.CollectionMapper;
import com.ls.fw.office.poi.excel.handler.ExcelHandler;
import com.ls.fw.office.poi.excel.handler.IExcelHandler;
import com.ls.fw.office.poi.excel.handler.IExcelHandler.RowColMapper;
import com.ls.fw.office.poi.excel.support.mapper.CellMapper;
import com.ls.fw.office.poi.excel.support.mapper.RowColNameMapper;
import com.ls.fw.office.poi.utils.PoiPublicUtil;
import com.ls.fw.office.poi.utils.PoiReflectorUtil;

/**
 * 
 * @author lisheng
 * @date 2015年10月8日 下午10:16:44
 * @version V1.0
 */
public class ExcelImport {
	
	protected IExcelHandler handler = null;
	
	protected Map<Integer,String> headMap;
	
	protected int headIndex;
	protected int rowFirstIndex = 1;
	protected int colFirstIndex = 0;

	protected int sheetNum = -1;
	
	public ExcelImport(InputStream input) {
		this.handler = new ExcelHandler(input);
	}
	
	public ExcelImport(String path, int headIndex) {
		this.handler = new ExcelHandler(path,true);
		this.headIndex = headIndex;
		this.rowFirstIndex = headIndex + 1;
	}

	public ExcelImport(InputStream input, int headIndex) {
		this.handler = new ExcelHandler(input);
		this.headIndex = headIndex;
		this.rowFirstIndex = headIndex + 1;
	}
	
	public ExcelImport(String path) {
		this.handler = new ExcelHandler(path,true);
	} 

	
	public void scan(final RowColNameMapper mapper) {
		handler.scan(rowFirstIndex, colFirstIndex, new RowColMapper() {
			
			@Override
			public void mapper(int rowIndex, int colIndex, Object value) {
				String keyString = ""+colIndex;
				if(headMap != null && headMap.containsKey(colIndex)){
					keyString = headMap.get(colIndex);
				}  
				mapper.mapper(rowIndex, colIndex, keyString, value);
			}
		});
	}
	
	/**
	 * 
	 * @author lisheng
	 * @date 2015年10月8日 下午10:23:08
	 * @version V1.0
	 * @param classType
	 * @param mapper
	 * @return
	 */
	public <T> List<T> toEntitys(final Class<T> classType, final CellMapper mapper) {
		final List<T> list  = new ArrayList<T>();
		final Field[] fsFields = PoiPublicUtil.getClassFields(classType);
		handler.scan(rowFirstIndex, colFirstIndex, new RowColMapper() {
			
			@Override
			public void mapper(int rowIndex, int colIndex, Object value) {
				T obj = null;
				if(list.size() >= rowIndex+1){
					obj = list.get(rowIndex);
				}else{;
					try {
						obj = classType.newInstance();
					} catch (InstantiationException e) {
					    throw new IllegalArgumentException(e);
					} catch (IllegalAccessException e) {
					    throw new IllegalArgumentException(e);
					}
					list.add(obj);
				}
				String keyString = ""+colIndex;
				if(headMap != null && headMap.containsKey(colIndex)){
					keyString = headMap.get(colIndex);
				}else{
					keyString= fsFields[colIndex].getName();
				}
				PoiReflectorUtil d = PoiReflectorUtil.forClass(classType);
				if(mapper !=null){
					d.setValue(obj, keyString, mapper.mapper(colIndex, keyString, value));
				}else{
					d.setValue(obj, keyString, value);
				}
			}
		});
		return list;
	}
	
	/**
	 * 
	 * @author lisheng
	 * @date 2016年6月15日 下午9:56:49
	 * @version V1.0
	 * @return
	 */
	public List<Map> toMap(){
		return toMap(null);
	}
	
	/**
	 * 
	 * @author lisheng
	 * @date 2016年6月15日 下午9:56:52
	 * @version V1.0
	 * @param mapper
	 * @return
	 */
	public List<Map> toMap(final CellMapper mapper){
		final List<Map> list  = new ArrayList<>();
		handler.scan(sheetNum,rowFirstIndex, colFirstIndex, new RowColMapper() {
			
			@Override
			public void mapper(int rowIndex, int colIndex, Object value) {
				Map<String, Object> map = null;
				if(list.size() >= rowIndex+1){
					map = list.get(rowIndex);
				}else{;
					map = new HashMap<String, Object>();
					list.add(map);
				}
				String keyString = ""+colIndex;
				if(headMap != null && headMap.containsKey(colIndex)){
					keyString = headMap.get(colIndex);
				}
				map.put(keyString, value);
				if(mapper !=null){
					map.put(keyString, mapper.mapper(colIndex, keyString, value));
				}else{
					map.put(keyString, value);
				}
			}
		});
		return list;
	}
 

	public <T> List<T>  toEntitys(final Class<T> classType){
		return toEntitys(classType, null);
	} 
	
	public IExcelHandler getHandler() {
		return handler;
	}

	public ExcelImport setHandler(IExcelHandler handler) {
		this.handler = handler;
		return this;
	}

	public Map<Integer, String> getHeadMap() {
		return this.headMap;
	}

	public ExcelImport setHeadMap(Map<Integer, String> headMap) {
		this.headMap = headMap;
		return this;
	}
	
	
	/**
	 * 将headIndex行作为head
	 * @author lisheng
	 * @date 2016年6月15日 下午9:08:14
	 * @version V1.0
	 * @param headIndex
	 * @throws Exception
	 */
	public ExcelImport setHead(int headIndex) throws Exception{
		Map<Integer,Object> map = this.handler.getRowMap(headIndex);
		MapUtils.traversal(map, new CollectionMapper() {
			
			@Override
			public boolean next(Object key, Object value) {
				if(headMap==null){
					headMap = new HashMap<Integer,String>();
				}
				headMap.put(Integer.valueOf(String.valueOf(key)), String.valueOf(value));
				return true;
			}
		});
		return this;
	}
	
	
	public ExcelImport setHead(String... heads){
		if(headMap==null){
			headMap = new HashMap<Integer,String>();
		}
		int index = 0;
		if(heads!=null){
			for (String string : heads) {
				headMap.put(index++, string);
			}
		}
		return this;
	}

	public int getHeadIndex() {
		return this.headIndex;
	}

	public ExcelImport setHeadIndex(int headIndex) {
		this.headIndex = headIndex;
		return this;
	}

	public int getRowFirstIndex() {
		return this.rowFirstIndex;
	}

	public ExcelImport setRowFirstIndex(int rowFirstIndex) {
		this.rowFirstIndex = rowFirstIndex;
		return this;
	}

	public int getColFirstIndex() {
		return this.colFirstIndex;
	}

	public ExcelImport setColFirstIndex(int colFirstIndex) {
		this.colFirstIndex = colFirstIndex;
		return this;
	}

	public int getSheetNum() {
		return this.sheetNum;
	}

	public ExcelImport setSheetNum(int sheetNum) {
		this.sheetNum = sheetNum;
		return this;
	}
}